home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / tcsh / Source / tc.prompt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  12.7 KB  |  534 lines

  1. /* $Header: /u/christos/src/tcsh-6.03/RCS/tc.prompt.c,v 3.16 1992/10/14 20:19:19 christos Exp $ */
  2. /*
  3.  * tc.prompt.c: Prompt printing stuff
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: tc.prompt.c,v 3.16 1992/10/14 20:19:19 christos Exp $")
  40.  
  41. #include "ed.h"
  42.  
  43. /*
  44.  * kfk 21oct1983 -- add @ (time) and / ($cwd) in prompt.
  45.  * PWP 4/27/87 -- rearange for tcsh.
  46.  * mrdch@com.tau.edu.il 6/26/89 - added ~, T and .# - rearanged to switch()
  47.  *                 instead of if/elseif
  48.  * Luke Mewburn, s902113@minyos.xx.rmit.OZ.AU 6-Sep-91 - changed date format
  49.  */
  50.  
  51. char   *month_list[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  52.             "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  53. char   *day_list[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
  54. void
  55. printprompt(promptno, str)
  56.     int     promptno;
  57.     char   *str;
  58. {
  59.     static  Char *ocp = NULL;
  60.     static  char *ostr = NULL;
  61.     time_t  lclock = time(NULL);
  62.     Char   *cp;
  63.  
  64.     switch (promptno) {
  65.     default:
  66.     case 0:
  67.     cp = value(STRprompt);
  68.     break;
  69.     case 1:
  70.     cp = value(STRprompt2);
  71.     break;
  72.     case 2:
  73.     cp = value(STRprompt3);
  74.     break;
  75.     case 3:
  76.     if (ocp != NULL) {
  77.         cp = ocp;
  78.         str = ostr;
  79.     }
  80.     else 
  81.         cp = value(STRprompt);
  82.     break;
  83.     }
  84.  
  85.     if (promptno < 2) {
  86.     ocp = cp;
  87.     ostr = str;
  88.     }
  89.  
  90.     PromptBuf[0] = '\0';
  91.     tprintf(FMT_PROMPT, PromptBuf, cp, 2 * INBUFSIZE - 2, str, lclock, NULL);
  92.  
  93.     if (!editing) {
  94.     for (cp = PromptBuf; *cp ; )
  95.         (void) putraw(*cp++);
  96.     SetAttributes(0);
  97.     flush();
  98.     }
  99. }
  100.  
  101. void
  102. tprintf(what, buf, fmt, siz, str, tim, info)
  103.     int what;
  104.     Char *buf, *fmt;
  105.     size_t siz;
  106.     char *str;
  107.     time_t tim;
  108.     ptr_t info;
  109. {
  110.     Char   *z, *q;
  111.     Char    attributes = 0;
  112.     static int print_prompt_did_ding = 0;
  113.     char   *cz;
  114.     Char    buff[BUFSIZE];
  115.     char    cbuff[BUFSIZE];
  116.  
  117.     Char *p  = buf;
  118.     Char *ep = &p[siz];
  119.     Char *cp = fmt;
  120.     struct tm *t = localtime(&tim);
  121.  
  122.     for (; *cp; cp++) {
  123.     if (p >= ep)
  124.         break;
  125.     if (*cp == '%') {
  126.         cp++;
  127.         switch (*cp) {
  128.         case 'R':
  129.         if (what == FMT_HISTORY)
  130.             fmthist('R', info, str = cbuff);
  131.         if (str != NULL)
  132.             while (*str) {
  133.             *p++ = attributes | *str++;
  134.             if (p >= ep) break;
  135.             }
  136.         break;
  137.         case '#':
  138.         *p++ = attributes | ((uid == 0) ? '#' : '>');
  139.         break;
  140.         case '!':
  141.         case 'h':
  142.         if (what == FMT_HISTORY)  
  143.             fmthist('h', info, cbuff);
  144.         else 
  145.             xsprintf(cbuff, "%d", eventno + 1);
  146.         for (cz = cbuff; *cz; cz++) {
  147.             *p++ = attributes | *cz;
  148.             if (p >= ep) break;
  149.         }
  150.         break;
  151.         case 'T':        /* 24 hour format     */
  152.         case '@':
  153.         case 't':        /* 12 hour am/pm format */
  154.         {
  155.             char    ampm = 'a';
  156.             int     hr = t->tm_hour;
  157.  
  158.             if (p >= ep - 10) break;
  159.  
  160.             /* addition by Hans J. Albertsson */
  161.             /* and another adapted from Justin Bur */
  162.             if (adrof(STRampm) || *cp != 'T') {
  163.             if (hr >= 12) {
  164.                 if (hr > 12)
  165.                 hr -= 12;
  166.                 ampm = 'p';
  167.             }
  168.             else if (hr == 0)
  169.                 hr = 12;
  170.             }        /* else do a 24 hour clock */
  171.  
  172.             /* "DING!" stuff by Hans also */
  173.             if (t->tm_min || print_prompt_did_ding || 
  174.             what != FMT_PROMPT) {
  175.             if (t->tm_min)
  176.                 print_prompt_did_ding = 0;
  177.             Itoa(hr, buff);
  178.             *p++ = attributes | buff[0];
  179.             if (buff[1]) 
  180.                 *p++ = attributes | buff[1];
  181.             *p++ = attributes | ':';
  182.             Itoa(t->tm_min, buff);
  183.             if (buff[1]) {
  184.                 *p++ = attributes | buff[0];
  185.                 *p++ = attributes | buff[1];
  186.             }
  187.             else {
  188.                 *p++ = attributes | '0';
  189.                 *p++ = attributes | buff[0];
  190.             }
  191.             if (adrof(STRampm) || *cp != 'T') {
  192.                 *p++ = attributes | ampm;
  193.                 *p++ = attributes | 'm';
  194.             }
  195.             }
  196.             else {    /* we need to ding */
  197.             int     i = 0;
  198.  
  199.             (void) Strcpy(buff, STRDING);
  200.             while (buff[i]) {
  201.                 *p++ = attributes | buff[i++];
  202.             }
  203.             print_prompt_did_ding = 1;
  204.             }
  205.         }
  206.         break;
  207.  
  208.         case 'M':
  209. #ifndef HAVENOUTMP
  210.         if (what == FMT_WHO)
  211.             cz = who_info(info, 'M', cbuff);
  212.         else 
  213. #endif /* HAVENOUTMP */
  214.             cz = getenv("HOST");
  215.         /*
  216.          * Bug pointed out by Laurent Dami <dami@cui.unige.ch>: don't
  217.          * derefrence that NULL (if HOST is not set)...
  218.          */
  219.         if (cz != NULL)
  220.             while (*cz) {
  221.             if (p >= ep) break;
  222.             *p++ = attributes | *cz++;
  223.             }
  224.         break;
  225.  
  226.         case 'm':
  227. #ifndef HAVENOUTMP
  228.         if (what == FMT_WHO)
  229.             cz = who_info(info, 'm', cbuff);
  230.         else 
  231. #endif /* HAVENOUTMP */
  232.             cz = getenv("HOST");
  233.  
  234.         if (cz != NULL)
  235.             while (*cz && (what == FMT_WHO || *cz != '.')) {
  236.             if (p >= ep) break;
  237.             *p++ = attributes | *cz++;
  238.             }
  239.         break;
  240.  
  241.         case '~':        /* show ~ whenever possible - a la dirs */
  242.         {
  243.             static Char *olddir = 0, *olduser = 0, *oldpath = 0;
  244.             extern int tlength;    /* cache cleared */
  245.  
  246.             if ((z = value(STRcwd)) == STRNULL)
  247.             break;    /* no cwd, so don't do anything */
  248.             /*
  249.              * Have we changed directory?
  250.              */
  251.             if (tlength == 0 || olddir != z) {
  252.             oldpath = olddir = z;
  253.             olduser = getusername(&oldpath);
  254.             }
  255.             if (olduser) {
  256.             *p++ = attributes | '~';
  257.             if (p >= ep) break;
  258.             for (q = olduser; *q; *p++ = attributes | *q++)
  259.                 if (p >= ep) break;
  260.             for (z = oldpath; *z; *p++ = attributes | *z++)
  261.                 if (p >= ep) break;
  262.             break;
  263.             }
  264.         }
  265.         /*FALLTHROUGH*/
  266.         case '/':
  267.         if ((z = value(STRcwd)) != STRNULL) {
  268.             while (*z) {
  269.             *p++ = attributes | *z++;
  270.             if (p >= ep) break;
  271.             }
  272.         }
  273.         break;
  274.         case '.':
  275.         case 'c':
  276.         case 'C':
  277.         {
  278.             register int j, k;
  279.             Char    scp;
  280.  
  281.             /* modified RWM 8/6/92 - indicate dirs ignored */
  282.             register int updirs;
  283.             int pdirs = 0;
  284.             
  285.             scp = *cp;
  286.             /* option to determine fix number of dirs from path */
  287.             if (*(cp + 1) == '0') {
  288.             pdirs = 1;
  289.             cp++;
  290.             }
  291.             if (*(cp + 1) >= '1' && *(cp + 1) <= '9') {
  292.             j = *(cp + 1) - '0';
  293.             cp++;
  294.             }
  295.             else {
  296.             j = 1;
  297.             }
  298.             if ((z = value(STRcwd)) == STRNULL)
  299.             break;
  300.             (void) Strcpy(buff, z);
  301.             if (!buff[1]) /* if CWD == / */
  302.             *p++ = attributes | buff[0];
  303.             else {
  304.             if ((scp != 'C') && (q = value(STRhome)) != STRNULL &&
  305.                 Strncmp(buff, q, (k = Strlen(q))) == 0 &&
  306.                 (buff[k] == '/' || buff[k] == '\0')) {
  307.                 buff[--k] = '~';
  308.                 q = &buff[k];
  309.                 /* RWM - reset the path length */
  310.                 updirs = 0;
  311.             }
  312.             else {
  313.                 q = buff;
  314.                 /* RWM - in case first char is not '/' */
  315.                 if (*q == '/') updirs = 0; else updirs = 1;
  316.             }
  317.             /* RWM - calculate elements in the path */
  318.             for (z = q; *z; z++) {
  319.                 if (*z == '/') updirs++;
  320.                 continue;    /* find the end */
  321.             }
  322.             /* RWM - the ones we will skip can be found here */
  323.             updirs -= j;
  324.             
  325.             while (j-- > 0) {
  326.                 while ((z > q) && (*z != '/'))
  327.                 z--;    /* back up */
  328.                 if (j && z > q)
  329.                 z--;
  330.             }
  331.             if (*z == '/' && z != q)
  332.                 z++;
  333.  
  334.             /* RWM - if *q == '~' and *z != '~' then print */
  335.             /*       out the '~' ahead of the partial path */
  336.             if (pdirs && (*q == '~') && (*z != '~'))
  337.                 *p++ = attributes | '~';
  338.             
  339.             /* RWM - tell you how many dirs we've ignored */
  340.             /*       and add '/' at front of this         */
  341.             if (updirs > 0 && pdirs) {
  342.                 *p++ = attributes | '/';
  343.                 *p++ = attributes | '<';
  344.                 if (updirs > 9) {
  345.                 *p++ = attributes | '9';
  346.                 *p++ = attributes | '+';
  347.                 } else
  348.                 *p++ = attributes | ('0' + updirs);
  349.                 *p++ = attributes | '>';
  350.             }
  351.             /* RWM - end of added code */
  352.  
  353.             while (*z) {
  354.                 *p++ = attributes | *z++;
  355.                 if (p >= ep) break;
  356.             }
  357.             }
  358.         }
  359.         break;
  360.         case 'n':
  361. #ifndef HAVENOUTMP
  362.         if (what == FMT_WHO) {
  363.             if ((cz = who_info(info, 'n', cbuff)) != NULL)
  364.             while (*cz) {
  365.                 *p++ = attributes | *cz++;
  366.                 if (p >= ep) break;
  367.             }
  368.         }
  369.         else  
  370. #endif /* HAVENOUTMP */
  371.         {
  372.             if ((z = value(STRuser)) != STRNULL)
  373.             while (*z) {
  374.                 *p++ = attributes | *z++;
  375.                 if (p >= ep) break;
  376.             }
  377.         }
  378.         break;
  379.         case 'l':
  380. #ifndef HAVENOUTMP
  381.         if (what == FMT_WHO) {
  382.             if ((cz = who_info(info, 'l', cbuff)) != NULL)
  383.             while (*cz) {
  384.                 *p++ = attributes | *cz++;
  385.                 if (p >= ep) break;
  386.             }
  387.         }
  388.         else  
  389. #endif /* HAVENOUTMP */
  390.         {
  391.             if ((z = value(STRtty)) != STRNULL)
  392.             while (*z) {
  393.                 *p++ = attributes | *z++;
  394.                 if (p >= ep) break;
  395.             }
  396.         }
  397.         break;
  398.         case 'd':
  399.         for (cz = day_list[t->tm_wday]; *cz;) {
  400.             *p++ = attributes | *cz++;
  401.             if (p >= ep) break;
  402.         }
  403.         break;
  404.         case 'D':
  405.         Itoa(t->tm_mday, buff);
  406.         if (p >= ep - 3) break;
  407.         if (buff[1]) {
  408.             *p++ = attributes | buff[0];
  409.             *p++ = attributes | buff[1];
  410.         }
  411.         else {
  412.             *p++ = attributes | '0';
  413.             *p++ = attributes | buff[0];
  414.         }
  415.         break;
  416.         case 'w':
  417.         if (p >= ep - 20) break;
  418.         for (cz = month_list[t->tm_mon]; *cz;) 
  419.             *p++ = attributes | *cz++;
  420.         break;
  421.         case 'W':
  422.         if (p >= ep - 3) break;
  423.         Itoa(t->tm_mon + 1, buff);
  424.         if (buff[1]) {
  425.             *p++ = attributes | buff[0];
  426.             *p++ = attributes | buff[1];
  427.         }
  428.         else {
  429.             *p++ = attributes | '0';
  430.             *p++ = attributes | buff[0];
  431.         }
  432.         break;
  433.         case 'y':
  434.         if (p >= ep - 3) break;
  435.         Itoa(t->tm_year, buff);
  436.         if (buff[1]) {
  437.             *p++ = attributes | buff[0];
  438.             *p++ = attributes | buff[1];
  439.         }
  440.         else {
  441.             *p++ = attributes | '0';
  442.             *p++ = attributes | buff[0];
  443.         }
  444.         break;
  445.         case 'Y':
  446.         if (p >= ep - 5) break;
  447.         Itoa(t->tm_year + 1900, buff);
  448.         *p++ = attributes | buff[0];
  449.         *p++ = attributes | buff[1];
  450.         *p++ = attributes | buff[2];
  451.         *p++ = attributes | buff[3];
  452.         break;
  453.         case 'S':        /* start standout */
  454.         attributes |= STANDOUT;
  455.         break;
  456.         case 'B':        /* start bold */
  457.         attributes |= BOLD;
  458.         break;
  459.         case 'U':        /* start underline */
  460.         attributes |= UNDER;
  461.         break;
  462.         case 's':        /* end standout */
  463.         attributes &= ~STANDOUT;
  464.         break;
  465.         case 'b':        /* end bold */
  466.         attributes &= ~BOLD;
  467.         break;
  468.         case 'u':        /* end underline */
  469.         attributes &= ~UNDER;
  470.         break;
  471.         case 'L':
  472.         ClearToBottom();
  473.         break;
  474.         case '?':
  475.         if ((z = value(STRstatus)) != STRNULL)
  476.             while (*z) {
  477.             *p++ = attributes | *z++;
  478.             if (p >= ep) break;
  479.             }
  480.         break;
  481.         case '%':
  482.         *p++ = attributes | '%';
  483.         break;
  484.         case '{':        /* literal characters start */
  485. #if LITERAL == 0
  486.         /*
  487.          * No literal capability, so skip all chars in the literal
  488.          * string
  489.          */
  490.         while (*cp != '\0' && (*cp != '%' || cp[1] != '}'))
  491.             cp++;
  492. #endif                /* LITERAL == 0 */
  493.         attributes |= LITERAL;
  494.         break;
  495.         case '}':        /* literal characters end */
  496.         attributes &= ~LITERAL;
  497.         break;
  498.         default:
  499. #ifndef HAVENOUTMP
  500.         if (*cp == 'a' && what == FMT_WHO) {
  501.             cz = who_info(info, 'a', cbuff);
  502.             while (*cz) {
  503.             *p++ = attributes | *cz++;
  504.             if (p >= ep) break;
  505.             }
  506.         }
  507.         else 
  508. #endif /* HAVENOUTMP */
  509.         {
  510.             if (p >= ep - 3) break;
  511.             *p++ = attributes | '%';
  512.             *p++ = attributes | *cp;
  513.         }
  514.         break;
  515.         }
  516.     }
  517.     else if (*cp == '\\' || *cp == '^') 
  518.         *p++ = attributes | parseescape(&cp);
  519.     else if (*cp == '!') {    /* EGS: handle '!'s in prompts */
  520.         if (what == FMT_HISTORY) 
  521.         fmthist('h', info, cbuff);
  522.         else
  523.         xsprintf(cbuff, "%d", eventno + 1);
  524.         for (cz = cbuff; *cz; cz++) {
  525.         *p++ = attributes | *cz;
  526.         if (p >= ep) break;
  527.         }
  528.     }
  529.     else 
  530.         *p++ = attributes | *cp;    /* normal character */
  531.     }
  532.     *p = '\0';
  533. }
  534.